import { _decorator, Component, Node, UITransform, Sprite, Animation, SpriteFrame, AnimationClip, animation } from 'cc'
const { ccclass, property } = _decorator

// 引入事件中心
import EventManager from '../../Runtime/EventManager'
import DataManager from '../../Runtime/DataManager'

// 实体类型
import { EntityManager } from '../../Base/EntityManager'
import { IEntity } from '../../Levels'

// 状态机
import { PlayerStateMchine } from './PlayerStateMchine'

// 状态机类型
import {  PLAYER_STATE_TYPE_ENUM,  } from '../../Enums'


// 人物移动的步长
const STEP = 1 / 10

import { DIRECTION } from '../../Enums'


@ccclass('PlayerManager')
export class PlayerManager extends EntityManager {
  targetX: number = 0
  targetY: number = 0
  // 开始移动
  _startMoveing: boolean = false

  async init(params: IEntity) {
    // 初始化状态机
    this.fsm = this.addComponent(PlayerStateMchine)
    await this.fsm.init()

    // 传入默认值
    super.init(params)

    this.targetX = this.x
    this.targetY = this.y
    // this.direction = DIRECTION.TOP
    // this.state = PLAYER_STATE_TYPE_ENUM.IDLE

    // 注册事件
    EventManager.Instance.on('DIRECTION', this.inputHandler, this)
    EventManager.Instance.on('ATTACK_PLAYER', this.onDeath, this)
  }

  onDestroy(): void {
    super.onDestroy()

    // 移除
    EventManager.Instance.off('DIRECTION', this.inputHandler, )
    EventManager.Instance.off('ATTACK_PLAYER', this.onDeath, )
  }

  // 每帧更新
  update() {
    this.updateXY()
    super.update()
    // this.node.setPosition(this.x * TILE_WIDTH - 1.5 * TILE_WIDTH, -this.y * TILE_HEIGHT + 1.5 * TILE_HEIGHT)
  }

  updateXY() {
    if (this.targetX < this.x) {
      this.x -= STEP
    } else if (this.targetX > this.x) {
      this.x += STEP
    }

    if (this.targetY < this.y) {
      this.y -= STEP
    } else if (this.targetY > this.y) {
      this.y += STEP
    }
    // 判断最后是否到达目标点，无限接近
    const infinitesimal = 0.1
    if (Math.abs(this.targetX - this.x) <= infinitesimal && Math.abs(this.targetY - this.y) <= infinitesimal && this._startMoveing) {
      this._startMoveing = false //立马停止
      this.x = this.targetX
      this.y = this.targetY
      EventManager.Instance.emit('PLAYER_MOVE_END')
    }
  }

  // 根据输入移动
  inputHandler(inputDirection: DIRECTION) {
    // 判断是否在移动
    if(this._startMoveing) {
      return
    }

    // 判断用户是否死亡
    if([PLAYER_STATE_TYPE_ENUM.DEATH, PLAYER_STATE_TYPE_ENUM.AIR_DEATH, PLAYER_STATE_TYPE_ENUM.ATTACK].indexOf(this.state) > -1) {
      return
    }

    // 判断是否攻击敌人
    const woodenskeletonId = this.isAttackWoodenskeleton(inputDirection)
    if(woodenskeletonId) {
      EventManager.Instance.emit('RECORD') //记录数据
      this.state = PLAYER_STATE_TYPE_ENUM.ATTACK
      EventManager.Instance.emit('ATTACK_SKELETON', woodenskeletonId)
      EventManager.Instance.emit('DOOR_OPEN', )
      EventManager.Instance.emit('PLAYER_MOVE_END')
      return
    }

    // 判断是否相撞
    if (this.collideBlock(inputDirection)) {
      this.onShake(inputDirection)
      return
    }
    this.moveTo(inputDirection)
  }

  onShake(inputDirection: DIRECTION) {
    // 震动的方向
    let direction = inputDirection
   if(inputDirection === DIRECTION.TURN_LEFT) {
      // direction = DIRECTION.TURN_LEFT
      if(this.direction === DIRECTION.TOP) {
        direction = DIRECTION.LEFT
      } else if(this.direction === DIRECTION.LEFT) {
        direction = DIRECTION.BOTTOM
      } else if(this.direction === DIRECTION.BOTTOM) {
        direction = DIRECTION.RIGHT
      } else if(this.direction === DIRECTION.RIGHT) {
        direction = DIRECTION.TOP
      }
    } else if(inputDirection === DIRECTION.TURN_RIGHT) {
      // direction = DIRECTION.TURN_RIGHT
      if(this.direction === DIRECTION.TOP) {
        direction = DIRECTION.RIGHT
      } else if(this.direction === DIRECTION.LEFT) {
        direction = DIRECTION.TOP
      } else if(this.direction === DIRECTION.BOTTOM) {
        direction = DIRECTION.LEFT
      } else if(this.direction === DIRECTION.RIGHT) {
        direction = DIRECTION.BOTTOM
      }
    }
    EventManager.Instance.emit('SHAKE', direction)
  }

  // 开始移动
  moveTo(inputDirection: DIRECTION) {
    EventManager.Instance.emit('RECORD') //记录数据
    if (inputDirection === DIRECTION.TOP) {
      this.targetY -= 1
      this._startMoveing = true
      // this.showSmoke(inputDirection)
      this.showSmoke(DIRECTION.TOP)
    } else if (inputDirection === DIRECTION.BOTTOM) {
      this.targetY += 1
      this._startMoveing = true
      // this.showSmoke(inputDirection)
      this.showSmoke(DIRECTION.BOTTOM)
    } else if (inputDirection === DIRECTION.LEFT) {
      this.targetX -= 1
      this._startMoveing = true
      // this.showSmoke(inputDirection)
      this.showSmoke(DIRECTION.LEFT)
    } else if (inputDirection === DIRECTION.RIGHT) {
      this.targetX += 1
      this._startMoveing = true
      // this.showSmoke(inputDirection)
      this.showSmoke(DIRECTION.RIGHT)
    } else if (inputDirection === DIRECTION.TURN_LEFT) {
      // 改变人物的方向
      if (this.direction === DIRECTION.TOP) {
        this.direction = DIRECTION.LEFT
      } else if (this.direction === DIRECTION.LEFT) {
        this.direction = DIRECTION.BOTTOM
      } else if (this.direction === DIRECTION.BOTTOM) {
        this.direction = DIRECTION.RIGHT
      } else if (this.direction === DIRECTION.RIGHT) {
        this.direction = DIRECTION.TOP
      }
      this.state = PLAYER_STATE_TYPE_ENUM.TURN_LEFT
      EventManager.Instance.emit('PLAYER_MOVE_END')
    } else if (inputDirection === DIRECTION.TURN_RIGHT) {
      // 改变人物的方向
      if (this.direction === DIRECTION.TOP) {
        this.direction = DIRECTION.RIGHT
      } else if (this.direction === DIRECTION.LEFT) {
        this.direction = DIRECTION.TOP
      } else if (this.direction === DIRECTION.BOTTOM) {
        this.direction = DIRECTION.LEFT
      } else if (this.direction === DIRECTION.RIGHT) {
        this.direction = DIRECTION.BOTTOM
      }
      this.state = PLAYER_STATE_TYPE_ENUM.TURN_RIGHT
      EventManager.Instance.emit('PLAYER_MOVE_END')
    }
  }

  // 判断是否相撞
  collideBlock(inputDirection: DIRECTION) {
    const tileInfo = DataManager.Instance.tileInfo
    const { mapRowCount: row, mapColCount: column } = DataManager.Instance
    const { targetX: x, targetY: y, direction } = this

    // 获取门
    const {x:doorX, y:doorY, state:doorState} = DataManager.Instance.door
    // 判断敌人
    const woodenskeletonsOld = DataManager.Instance.woodenskeletons
    const woodenskeletons = woodenskeletonsOld.filter((item) => {
      return item?.state !== PLAYER_STATE_TYPE_ENUM.DEATH
    })
    let woodenskeletonsLen = woodenskeletons.length

    // 判断地裂
    const burstsOld = DataManager.Instance.bursts
    const bursts = burstsOld.filter((item) => {
      return item?.state !== PLAYER_STATE_TYPE_ENUM.DEATH
    })

    if (inputDirection === DIRECTION.TOP) {
      const playerNextY = y - 1
      if (playerNextY < 0) {
        this.state = PLAYER_STATE_TYPE_ENUM.BLOCKFRONT
        return true
      }
      if (direction === DIRECTION.TOP) {
        const weaponNextY = y - 2
        const nextPlayerTile = tileInfo[x]?.[playerNextY]
        const nextWeaponTile = tileInfo[x]?.[weaponNextY]

        // 判断跟门是否相撞
        if(doorState !== PLAYER_STATE_TYPE_ENUM.DEATH) {
          if((x === doorX && playerNextY === doorY) || (x === doorX && weaponNextY === doorY) ) {
            this.state = PLAYER_STATE_TYPE_ENUM.BLOCKFRONT
            return true
          }
        }

        // 判断是否跟敌人相撞
        for (let index = 0; index < woodenskeletonsLen; index++) {
          const element = woodenskeletons[index];
          let {x:skeletonX, y:skeletonY} = element
          if((x === skeletonX && playerNextY === skeletonY) || (x === skeletonX && weaponNextY === skeletonY) ) {
            this.state = PLAYER_STATE_TYPE_ENUM.BLOCKFRONT
            return true
          }
        }

        // 判断是否是地裂
        // 至少有一个满足条件
        if (bursts.some(burst => burst.x === x && burst.y === playerNextY) && (!nextWeaponTile || nextWeaponTile.turnable)) {
          return false
        }

        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKFRONT
          return true
        }
      } else if (direction === DIRECTION.LEFT) {
        const weaponNextX = x - 1
        const weaponNextY = y - 1
        const nextPlayerTile = tileInfo[x]?.[playerNextY]
        const nextWeaponTile = tileInfo[weaponNextX]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKLEFT
          return true
        }
      } else if (direction === DIRECTION.BOTTOM) {
        const weaponNextY = y
        const nextPlayerTile = tileInfo[x]?.[playerNextY]
        const nextWeaponTile = tileInfo[x]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKBACK
          return true
        }
      } else if (direction === DIRECTION.RIGHT) {
        const weaponNextX = x + 1
        const weaponNextY = y - 1
        const nextPlayerTile = tileInfo[x]?.[playerNextY]
        const nextWeaponTile = tileInfo[weaponNextX]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKRIGHT
          return true
        }
      }
    } else if (inputDirection === DIRECTION.LEFT) {
      const playerNextX = x - 1
      if (playerNextX < 0) {
        this.state = PLAYER_STATE_TYPE_ENUM.BLOCKLEFT
        return true
      }
      if (direction === DIRECTION.TOP) {
        const weaponNextX = x - 1
        const weaponNextY = y - 1
        const nextPlayerTile = tileInfo[playerNextX]?.[y]
        const nextWeaponTile = tileInfo[weaponNextX]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKLEFT
          return true
        }
      } else if (direction === DIRECTION.LEFT) {
        const weaponNextX = x - 2
        const nextPlayerTile = tileInfo[playerNextX]?.[y]
        const nextWeaponTile = tileInfo[weaponNextX]?.[y]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKFRONT
          return true
        }
      } else if (direction === DIRECTION.BOTTOM) {
        const weaponNextX = x - 1
        const weaponNextY = y + 1
        const nextPlayerTile = tileInfo[playerNextX]?.[y]
        const nextWeaponTile = tileInfo[weaponNextX]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKRIGHT
          return true
        }
      } else if (direction === DIRECTION.RIGHT) {
        const weaponNextX = x
        const nextPlayerTile = tileInfo[playerNextX]?.[y]
        const nextWeaponTile = tileInfo[weaponNextX]?.[y]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKBACK
          return true
        }
      }
    } else if (inputDirection === DIRECTION.RIGHT) {
      const playerNextX = x + 1
      if (playerNextX > row - 1) {
        this.state = PLAYER_STATE_TYPE_ENUM.BLOCKRIGHT
        return true
      }
      if (direction === DIRECTION.TOP) {
        const weaponNextX = x + 1
        const weaponNextY = y - 1
        const nextPlayerTile = tileInfo[playerNextX]?.[y]
        const nextWeaponTile = tileInfo[weaponNextX]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKRIGHT
          return true
        }
      } else if (direction === DIRECTION.LEFT) {
        const weaponNextX = x
        const nextPlayerTile = tileInfo[playerNextX]?.[y]
        const nextWeaponTile = tileInfo[weaponNextX]?.[y]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKBACK
          return true
        }
      } else if (direction === DIRECTION.BOTTOM) {
        const weaponNextX = x + 1
        const weaponNextY = y + 1
        const nextPlayerTile = tileInfo[playerNextX]?.[y]
        const nextWeaponTile = tileInfo[weaponNextX]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKLEFT
          return true
        }
      } else if (direction === DIRECTION.RIGHT) {
        const weaponNextX = x + 2
        const nextPlayerTile = tileInfo[playerNextX]?.[y]
        const nextWeaponTile = tileInfo[weaponNextX]?.[y]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKFRONT
          return true
        }
      }
    } else if (inputDirection === DIRECTION.BOTTOM) {
      const playerNextY = y + 1
      if (playerNextY > column - 1) {
        this.state = PLAYER_STATE_TYPE_ENUM.BLOCKBACK
        return true
      }
      if (direction === DIRECTION.TOP) {
        const weaponNextY = y
        const nextPlayerTile = tileInfo[x]?.[playerNextY]
        const nextWeaponTile = tileInfo[x]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKFRONT
          return true
        }
      } else if (direction === DIRECTION.LEFT) {
        const weaponNextX = x - 1
        const weaponNextY = y + 1
        const nextPlayerTile = tileInfo[x]?.[playerNextY]
        const nextWeaponTile = tileInfo[weaponNextX]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKLEFT
          return true
        }
      } else if (direction === DIRECTION.BOTTOM) {
        const weaponNextY = y + 2
        const nextPlayerTile = tileInfo[x]?.[playerNextY]
        const nextWeaponTile = tileInfo[x]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKBACK
          return true
        }
      } else if (direction === DIRECTION.RIGHT) {
        const weaponNextX = x + 1
        const weaponNextY = y + 1
        const nextPlayerTile = tileInfo[x]?.[playerNextY]
        const nextWeaponTile = tileInfo[weaponNextX]?.[weaponNextY]
        if (!(nextPlayerTile && nextPlayerTile.moveable && (!nextWeaponTile || nextWeaponTile.turnable))) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKRIGHT
          return true
        }
      }
    }

    // 判断转向
    if (inputDirection === DIRECTION.TURN_LEFT) {
      let nextX = 0
      let nextY = 0
      if (direction === DIRECTION.TOP) {
        nextX = x - 1
        nextY = y - 1
      } else if (direction === DIRECTION.LEFT) {
        nextX = x - 1
        nextY = y + 1
      } else if (direction === DIRECTION.BOTTOM) {
        nextX = x + 1
        nextY = y + 1
      } else if (direction === DIRECTION.RIGHT) {
        nextX = x + 1
        nextY = y - 1
      }

      // 判断跟门是否相撞
      if(doorState !== PLAYER_STATE_TYPE_ENUM.DEATH) {
        if((x === doorX && nextY === doorY) || (nextX === doorX && y === doorY) ||  (nextX === doorX && nextY === doorY)) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKFRONT
          return true
        }
      }

      // 判断是否跟敌人相撞
      for (let index = 0; index < woodenskeletonsLen; index++) {
        const element = woodenskeletons[index];
        let {x:skeletonX, y:skeletonY} = element
        if((x === skeletonX && nextY === skeletonY) || (nextX === skeletonX && y === skeletonY) ||  (nextX === skeletonX && nextY === skeletonY) ) {
          this.state = PLAYER_STATE_TYPE_ENUM.BLOCKFRONT
          return true
        }
      }

      if (
        !(
          (!tileInfo[x]?.[nextY] || tileInfo[x]?.[nextY].turnable) &&
          (!tileInfo[nextX]?.[y] || tileInfo[nextX]?.[y].turnable) &&
          (!tileInfo[nextX]?.[nextY] || tileInfo[nextX]?.[nextY].turnable)
        )
      ) {
        this.state = PLAYER_STATE_TYPE_ENUM.BLOCKTURNLEFT
        return true
      }
    } else if (inputDirection === DIRECTION.TURN_RIGHT) {
      let nextX = 0
      let nextY = 0
      if (direction === DIRECTION.TOP) {
        nextX = x + 1
        nextY = y - 1
      } else if (direction === DIRECTION.LEFT) {
        nextX = x - 1
        nextY = y - 1
      } else if (direction === DIRECTION.BOTTOM) {
        nextX = x - 1
        nextY = y + 1
      } else if (direction === DIRECTION.RIGHT) {
        nextX = x + 1
        nextY = y + 1
      }

      if (
        !(
          (!tileInfo[x]?.[nextY] || tileInfo[x]?.[nextY].turnable) &&
          (!tileInfo[nextX]?.[y] || tileInfo[nextX]?.[y].turnable) &&
          (!tileInfo[nextX]?.[nextY] || tileInfo[nextX]?.[nextY].turnable)
        )
      ) {
        this.state = PLAYER_STATE_TYPE_ENUM.BLOCKTURNRIGHT
        return true
      }
    }

    return false
  }

  // 被攻击死亡
  onDeath(type?:PLAYER_STATE_TYPE_ENUM) {
    // PLAYER_STATE_TYPE_ENUM.DEATH
    this.state = type
  }

  // 生成烟雾
  showSmoke(inputDirection: DIRECTION) {
    const { x, y } = this
    EventManager.Instance.emit('SHOW_SMOKE', x, y, inputDirection)
  }


  onTriggered(inputDirection: DIRECTION) {
    EventManager.Instance.emit('SHAKE', inputDirection)
  }

  // 是否攻击敌人
  isAttackWoodenskeleton(inputDirection: DIRECTION) {
    const {direction, targetX:playerX, targetY:playerY} = this
    const woodenskeletonsOld = DataManager.Instance.woodenskeletons
    // 只判断没有死亡的敌人
    const woodenskeletons = woodenskeletonsOld.filter((woodenskeleton) => {
      return woodenskeleton.state !== PLAYER_STATE_TYPE_ENUM.DEATH
    })

    const len = woodenskeletons.length

    for (let index = 0; index < len; index++) {
      const woodenskeleton = woodenskeletons[index];
      const {x:woodenskeletonX, y:woodenskeletonY, id:woodenskeletonId} = woodenskeleton
      if(inputDirection === DIRECTION.TOP && direction === DIRECTION.TOP && playerX === woodenskeletonX && playerY - 2 === woodenskeletonY ) {
        this.state = PLAYER_STATE_TYPE_ENUM.ATTACK
        return woodenskeletonId
      } else  if(inputDirection === DIRECTION.LEFT && direction === DIRECTION.LEFT && playerX - 2 === woodenskeletonX  && playerY === woodenskeletonY ) {
        this.state = PLAYER_STATE_TYPE_ENUM.ATTACK
        return woodenskeletonId
      } else  if(inputDirection === DIRECTION.BOTTOM && direction === DIRECTION.BOTTOM && playerX === woodenskeletonX  && playerY + 2 === woodenskeletonY  ) {
        this.state = PLAYER_STATE_TYPE_ENUM.ATTACK
        return woodenskeletonId
      }  else  if(inputDirection === DIRECTION.RIGHT && direction === DIRECTION.RIGHT && playerX + 2 === woodenskeletonX   && playerY === woodenskeletonY  ) {
        this.state = PLAYER_STATE_TYPE_ENUM.ATTACK
        return woodenskeletonId
      }
    }
    return ''
  }
}
